package com.example.utils;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

/**
 * 用于将语音的格式转为语音正确识别的格式
 * 解决了语音格式不对导致语音复刻和识别的问题
 */
public class WavMin {
    private static final int TARGET_SAMPLE_RATE = 16000;
    private static final int TARGET_SAMPLE_SIZE = 16;
    private static final int TARGET_CHANNELS = 1;

    /**
     * 将音频数据转换为符合实时语音识别要求的格式（16kHz, 16bit, 单声道）
     * @param audioData 原始音频数据
     * @return 转换后的音频数据
     */
    public static byte[] convertAudio(byte[] audioData) throws Exception {
        // 1. 将原始音频数据转换为输入流
        ByteArrayInputStream inputStream = new ByteArrayInputStream(audioData);
        
        // 2. 获取原始音频格式
        AudioFormat sourceFormat = AudioSystem.getAudioFileFormat(inputStream).getFormat();
        
        // 3. 创建目标音频格式
        AudioFormat targetFormat = new AudioFormat(
                TARGET_SAMPLE_RATE,
                TARGET_SAMPLE_SIZE,
                TARGET_CHANNELS,
                true,
                false
        );
        
        // 4. 创建音频输入流
        AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(inputStream);
        
        // 5. 转换音频格式
        AudioInputStream convertedStream = AudioSystem.getAudioInputStream(targetFormat, audioInputStream);
        
        // 6. 读取转换后的音频数据
        byte[] convertedData = convertedStream.readAllBytes();
        
        // 7. 关闭流
        audioInputStream.close();
        convertedStream.close();
        inputStream.close();

        // 8. 创建输出流并写入WAV文件头
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        writeWavHeader(outputStream, convertedData.length, targetFormat);
        outputStream.write(convertedData);
        
        // 9. 返回完整的WAV格式数据
        return outputStream.toByteArray();
    }

    /**
     * 写入WAV文件头
     * @param out 输出流
     * @param dataSize 音频数据大小
     * @param format 音频格式
     */
    private static void writeWavHeader(OutputStream out, int dataSize, AudioFormat format) throws IOException {
        // WAV文件头
        out.write("RIFF".getBytes());
        writeInt(out, 36 + dataSize); // 文件总大小
        out.write("WAVE".getBytes());
        out.write("fmt ".getBytes());
        writeInt(out, 16); // fmt块大小
        writeShort(out, 1); // 格式类型（PCM）
        writeShort(out, format.getChannels());
        writeInt(out, (int) format.getSampleRate());
        writeInt(out, (int) (format.getSampleRate() * format.getFrameSize()));
        writeShort(out, format.getFrameSize());
        writeShort(out, format.getSampleSizeInBits());
        out.write("data".getBytes());
        writeInt(out, dataSize);
    }

    /**
     * 写入32位整数（小端序）
     */
    private static void writeInt(OutputStream out, int value) throws IOException {
        ByteBuffer buffer = ByteBuffer.allocate(4);
        buffer.order(ByteOrder.LITTLE_ENDIAN);
        buffer.putInt(value);
        out.write(buffer.array());
    }

    /**
     * 写入16位整数（小端序）
     */
    private static void writeShort(OutputStream out, int value) throws IOException {
        ByteBuffer buffer = ByteBuffer.allocate(2);
        buffer.order(ByteOrder.LITTLE_ENDIAN);
        buffer.putShort((short) value);
        out.write(buffer.array());
    }
}